package org.jpropelleralt.jview.table.impl;

import java.awt.Color;
import java.util.concurrent.atomic.AtomicBoolean;

import javax.swing.Icon;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.event.TableModelEvent;
import javax.swing.table.TableColumnModel;
import javax.swing.table.TableModel;

import org.jpropelleralt.jview.JView;
import org.jpropelleralt.jview.general.impl.GeneralRendererDefault;
import org.jpropelleralt.jview.general.impl.GeneralRendererDefault.RenderFormat;
import org.jpropelleralt.jview.table.cell.impl.BooleanCellEditor;
import org.jpropelleralt.jview.table.cell.impl.BooleanCellRenderer;
import org.jpropelleralt.jview.table.cell.impl.ColorCellEditor;
import org.jpropelleralt.jview.table.cell.impl.ColorCellRenderer;
import org.jpropelleralt.jview.table.cell.impl.GeneralTableCellRenderer;
import org.jpropelleralt.jview.table.cell.impl.IconCellRenderer;
import org.jpropelleralt.jview.table.cell.impl.NumberCellEditor;
import org.jpropelleralt.jview.table.cell.impl.SelectingTextCellEditor;

/**
 * A {@link JTable} with better defaults,
 * and logic to support detecting when the
 * table is responding to a model change, to
 * prevent it messing with selection.
 * This makes it easier to use as a {@link JView}
 */
public class JViewTable extends JTable {

	private AtomicBoolean isRespondingToChange;
	
    /**
     * Constructs a default {@link JViewTable} that is initialized with a default
     * data model, a default column model, and a default selection
     * model.
     *
     * @see #createDefaultDataModel
     * @see #createDefaultColumnModel
     * @see #createDefaultSelectionModel
     */
	public JViewTable() {
		super();
		init();
	}

    /**
     * Constructs a {@link JViewTable} that is initialized with
     * <code>dm</code> as the data model, <code>cm</code> as the
     * column model, and <code>sm</code> as the selection model.
     * If any of the parameters are <code>null</code> this method
     * will initialize the table with the corresponding default model.
     * The <code>autoCreateColumnsFromModel</code> flag is set to false
     * if <code>cm</code> is non-null, otherwise it is set to true
     * and the column model is populated with suitable
     * <code>TableColumns</code> for the columns in <code>dm</code>.
     *
     * @param dm        the data model for the table
     * @param cm        the column model for the table
     * @param sm        the row selection model for the table
     * @see #createDefaultDataModel
     * @see #createDefaultColumnModel
     * @see #createDefaultSelectionModel
     */
	public JViewTable(TableModel dm, TableColumnModel cm, ListSelectionModel sm) {
		super(dm, cm, sm);
		init();
	}

    /**
     * Constructs a {@link JViewTable} that is initialized with
     * <code>dm</code> as the data model, <code>cm</code>
     * as the column model, and a default selection model.
     *
     * @param dm        the data model for the table
     * @param cm        the column model for the table
     * @see #createDefaultSelectionModel
     */
	public JViewTable(TableModel dm, TableColumnModel cm) {
		super(dm, cm);
		init();
	}

    /**
     * Constructs a {@link JViewTable} that is initialized with
     * <code>dm</code> as the data model, a default column model,
     * and a default selection model.
     *
     * @param dm        the data model for the table
     * @see #createDefaultColumnModel
     * @see #createDefaultSelectionModel
     */
	public JViewTable(TableModel dm) {
		super(dm);
		init();
	}
	
	private void init() {
		//Improved editors and renderers
		setDefaultEditor(Double.class, 		NumberCellEditor.doubleEditor());
		setDefaultEditor(Float.class, 		NumberCellEditor.floatEditor());
		setDefaultEditor(Integer.class, 	NumberCellEditor.integerEditor());
		setDefaultEditor(Long.class, 		NumberCellEditor.longEditor());
		setDefaultEditor(String.class, 		SelectingTextCellEditor.editor());
		
		setDefaultEditor(Color.class, 		new ColorCellEditor());
		setDefaultEditor(Boolean.class, 	new BooleanCellEditor());
		
		setDefaultRenderer(Icon.class, 		new IconCellRenderer());
		setDefaultRenderer(Color.class, 	new ColorCellRenderer());
		setDefaultRenderer(Boolean.class, 	BooleanCellRenderer.opaque());

		setDefaultRenderer(Object.class, new GeneralTableCellRenderer(new GeneralRendererDefault(RenderFormat.SINGLE_LINE)));
		
		//Set sensible row height
		setRowHeight(26);
	}
	
	@Override
	public void tableChanged(TableModelEvent e) {
		if (isRespondingToChange == null) {
			 isRespondingToChange = new AtomicBoolean(false);
		}
		isRespondingToChange.set(true);
		super.tableChanged(e);
		isRespondingToChange.set(false);
	}
	
	/**
	 * True if the table is responding to a change,
	 * false otherwise
	 * @return Whether table is responding to a change
	 */
	public boolean isRespondingToChange() {
		if (isRespondingToChange == null) {
			 isRespondingToChange = new AtomicBoolean(false);
		}
		return isRespondingToChange.get();
	}
}
